import cv2
import numpy as np

# 读取图像
input_path = r"C:\Users\Administrator\Desktop\lin_shi\mmexport1619842928785.jpg"
output_path = r"C:\Users\Administrator\Desktop\lin_shi\mmexport1619842928785_1.jpg"
img = cv2.imread(input_path)

if img is None:
  print("无法读取图像，请检查文件路径")
  exit()

points = []

def mouse_click(event, x, y, flags, param):
  global points
  if event == cv2.EVENT_LBUTTONDOWN:
    points.append([x, y])
    # 在显示的图像上绘制点，但不修改原图
    display_img = img.copy()
    for p in points:
      cv2.circle(display_img, tuple(p), 5, (0, 255, 0), -1)
    cv2.imshow(window_name, display_img)
    print(f"Selected point: ({x}, {y})")

window_name = 'Original Image'
cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
cv2.resizeWindow(window_name, 800, 600)
cv2.setMouseCallback(window_name, mouse_click)

# 显示原始图像
cv2.imshow(window_name, img)

while True:
  if cv2.waitKey(1) & 0xFF == ord('q'):
    break

if len(points) != 4:
  print('请选择恰好四个点。')
  exit()

# 确保点的顺序是左上、右上、右下、左下
src_points = np.float32(points)

# 计算源点形成的四边形的宽高比
src_width = np.linalg.norm(src_points[0] - src_points[1])
src_height = np.linalg.norm(src_points[1] - src_points[2])
aspect_ratio = src_width / src_height

# 根据源点的宽高比调整目标点的尺寸
dst_width = img.shape[1]  # 目标图像的宽度
dst_height = int(dst_width / aspect_ratio)  # 根据宽高比计算高度
dst_points = np.float32([[0, 0], [dst_width, 0], [dst_width, dst_height], [0, dst_height]])

# 计算透视变换矩阵
M = cv2.getPerspectiveTransform(src_points, dst_points)

# 应用透视变换，使用调整后的目标尺寸
warped_img = cv2.warpPerspective(img, M, (dst_width, dst_height))

# 检查透视变换结果
if warped_img is None or warped_img.size == 0:
  print("透视变换失败或生成的图像无效")
  exit()

# 调试信息：打印变换矩阵和图像尺寸
print(f"变换矩阵 M:\n{M}")
print(f"原图尺寸: {img.shape}")
print(f"变换后图像尺寸: {warped_img.shape}")

# 显示透视变换后的图像
warped_window_name = 'Warped Image'
cv2.namedWindow(warped_window_name, cv2.WINDOW_NORMAL)
cv2.resizeWindow(warped_window_name, 800, 600)
cv2.imshow(warped_window_name, warped_img)
print("显示透视变换后的图像...")

# 保存透视变换后的图像
cv2.imwrite(output_path, warped_img)
print(f"已保存透视变换后的图像到: {output_path}")

cv2.waitKey(0)
cv2.destroyAllWindows()
